package com.lobov.run;

import com.lobov.entities.ContainerOfSnips;
import com.lobov.entities.Matrix;
import com.lobov.entities.Snip;
import com.lobov.entities.Timer;
import com.lobov.operations.Multiplication;
import com.lobov.utils.Compressor;
import com.lobov.utils.Cutter;
import com.lobov.utils.Generator;
import com.lobov.utils.Parser;

/**
 * Класс тестовых запусков
 * 
 */
public class Run {

	private final static String NIXPATH = "/home/sanix/test.txt";

	private final static String WINPATH1 = "d:\\test1.txt";
	private final static String WINPATH2 = "d:\\test2.txt";

	// запуск научных методов расчета
	public static void main(String[] args) throws Exception {

		int h = 12;
		int val = 12;
		int endVal = 240;

		sc1(h, val, endVal);

		// sc2(50, 100, 100, 3, true);
		// sc2(50, 100, 100, 3, false);
	}

	// генерируем и перемножаем две матрицы
	public static void main22223(String[] args) throws Exception {
		System.out.println("Начинаем генерировать матрицу 1");
		Matrix m1 = Generator.generateUnCompressedHorisontalMatrix(5, 5, 0.2);
		System.out.println("Матрица 1 сгенерирована");
		System.out.println("Начинаем генерировать матрицу 2");
		Matrix m2 = Generator.generateUnCompressedHorisontalMatrix(5, 5, 0.2);
		System.out.println("Матрица 2 сгенерирована");
		Timer timer = new Timer();
		timer.startTimer();
		System.out.println("Умножаем матрицу 1 на матрицу 2 ...");
		Matrix m3 = Multiplication.newInstance().matrixOnMatrix(m1, m2, false);
		System.out.println("Перемножение закончено");
		System.out.println(m3);
		System.out.println("ВРЕМЯ РАСЧЕТА: " + timer.getTime() + " мс.");
	}

	// генерируем матрицу, создаем сжатую копию, перемножаем их и выводим обе на
	// печать
	public static void main3(String[] args) throws Exception {
		System.out.println("Начинаем генерировать матрицу 1");
		Matrix m1 = Generator.generateUnCompressedHorisontalMatrix(5, 5, 0.2);
		System.out.println("Матрица 1 сгенерирована");
		System.out.println("Получаем матрицу 2 сжатием матрицы 1");
		Matrix m2 = Compressor.compressMatrix(m1);
		System.out.println("Матрица 2 создана");
		System.out.println("\n Выводим матрицу 1: \n");
		System.out.println(m1);
		System.out.println("\n Выводим матрицу 2 (сжатый формат): \n");
		System.out.println(m2);
		System.out.println("\n Умножаем матрицу 1 на матрицу 1 ...");
		Matrix m3 = Multiplication.newInstance().matrixOnMatrix(m1, m1, false);
		System.out.println("\n Перемножение закончено");
		System.out.println(m3);
		System.out
				.println("\n Умножаем матрицу 1 (обычный формат) на матрицу 2 (сжатый формат) ...");
		Matrix m4 = Multiplication.newInstance().matrixOnMatrix(m1, m2, false);
		System.out.println("\n Перемножение закончено");
		System.out.println(m4);
	}

	// создаем две матрицы, сжимаем их, перемножаем сжатые и несжатые матрицы и
	// выводим разницу во времени расчета произведения
	public static void main99(String[] args) throws Exception {
		Matrix m1f = Generator.generateUnCompressedHorisontalMatrix(100, 100, 0.2);
		Matrix m1c = Compressor.compressMatrix(m1f);
		Matrix m2f = Generator.generateUnCompressedHorisontalMatrix(100, 100, 0.2);
		Matrix m2c = Compressor.compressMatrix(m2f);
		Multiplication mult1f = Multiplication.newInstance();
		Multiplication mult2c = Multiplication.newInstance();
		mult1f.matrixOnMatrix(m1f, m2f, true);
		mult2c.matrixOnMatrix(m1c, m2c, true);
		System.out.println("Разреженный формат умножался: " + mult1f.getTime()
				+ " мс");
		System.out.println("Сжатый формат умножался: " + mult2c.getTime()
				+ " мс");
	}

	// считываем и перемножаем две матрицы
	public static void main22(String[] args) throws Exception {
		Matrix m1 = Parser.parseFileToMatrix(WINPATH1, null);
		m1.setName("m1");
		System.out.println("матрица 1:  \n" + m1);
		Matrix m2 = Parser.parseFileToMatrix(WINPATH2, null);
		m2.setName("m2");
		System.out.println("матрица 2:  \n" + m2);
		Matrix m3 = Multiplication.newInstance().matrixOnMatrix(m1, m2, false);

		System.out.println("произведение: \n" + m3);

	}

	// считываем матрицу и выводим ее лоскуты, затем собираем матрицу из
	// лоскутов
	public static void main2222(String[] args) throws Exception {
		Matrix m1 = Parser.parseFileToMatrix(NIXPATH, null);
		m1.setName("m1");
		System.out.println("матрица 1:  \n" + m1);
		ContainerOfSnips cont = Cutter.cutMatrixHorizontal(m1, 3);
		int num = 1;
		for (Snip s : cont.getSnips()) {
			System.out.println("снип " + num + ": \n" + s);
			num++;
		}
		System.out.println("сам контейнер: \n" + cont.toMatrix()); // TODO
																	// разобраться!!!
	}

	// считываем матрицу и выводим ее лоскуты, сжимаем лоскуты, умножаем ту же
	// матрицу на лоскуты, затем собираем матрицу из
	// лоскутов-произведений; просто перемножаем матрицу саму на себя и
	// сравниваем время
	public static void main123(String[] args) throws Exception {
		Matrix m1 = Parser.parseFileToMatrix(NIXPATH, null);
		m1.setName("m1");
		System.out.println("матрица 1:  \n" + m1);
		ContainerOfSnips container = Cutter.cutMatrixHorizontal(m1, 4);
		ContainerOfSnips multContainer = new ContainerOfSnips(4,
				m1.getXlength());
		int num = 0;
		for (Snip s : container.getSnips()) {
			s = Compressor.compressSnip(s);
			System.out.println("Исходный лоскут " + num + ": \n" + s);
			Snip s2 = Multiplication.newInstance().snipOnMatrix(s, m1, false);
			System.out.println("Перемноженный лоскут " + num + ": \n" + s2);
			multContainer.setSnipByIndex(s2, num);
			num++;
		}

		Matrix m3multMatrix = Multiplication.newInstance().matrixOnMatrix(m1,
				m1, false);
		System.out.println("матрица 3 из перемножения матриц:  \n"
				+ m3multMatrix);
		Matrix m3multMatrixOnSnips = multContainer.toMatrix();
		System.out.println("матрица 3 из перемножения матрицы и лоскутов:  \n"
				+ m3multMatrixOnSnips);

		System.out.println("сам контейнер: \n" + container.toMatrix());
	}

	// генерируем матрицу, режем ее на лоскуты и выодим эти лоскуты на печать
	public static void main13(String[] args) throws Exception {
		Matrix m = Generator.generateUnCompressedHorisontalMatrix(9, 9, 0.2);

		System.out.println("Сгенерированная матрица: \n" + m + "\n");
		ContainerOfSnips container = Cutter.cutMatrixHorizontal(m, 3);
		System.out.println(container.getSnips().length);
		int size = container.getSnips().length;
		for (int i = 0; i < size; i++) {
			Snip s = container.getSnipByIndex(i);
			s = Compressor.compressSnip(s);
			System.out.println("Снип номер " + i + " : \n" + s + "\n");
		}
	}

	// генерируем матрицу, режем ее на лоскуты и умножаем каждый лоскут на
	// другую матрицу, а так же первую матрицу на ту же матрицу что и лоскуты
	// сравниваем результат
	public static void main222(String[] args) throws Exception {
		System.out.println("Генерируем матрицу 1 ...");
		Matrix m1 = Generator.generateUnCompressedHorisontalMatrix(1000, 1000, 0.2);
		System.out.println("Генерируем матрицу 2 ...");
		Matrix m2 = Generator.generateUnCompressedHorisontalMatrix(1000, 1000, 0.2);

		System.out.println("Сгенерированная матрица1: \n" + m1 + "\n");
		System.out.println("Сгенерированная матрица2: \n" + m2 + "\n");
		System.out
				.println("Режем матрицу 1 на лоскуты и помещаем их в контейнер ...");
		ContainerOfSnips container = Cutter.cutMatrixHorizontal(m1, 3);
		int size = container.getSnips().length;
		for (int i = 0; i < size; i++) {
			System.out.println("Снип номер " + i + " : \n"
					+ container.getSnipByIndex(i) + "\n");
		}
		System.out.println("Умножаем матрицу 1 на матрицу 2");
		Timer timer1 = new Timer();
		timer1.startTimer();
		Multiplication mult1 = Multiplication.newInstance();
		// Matrix m3 = mult1.matrixOnMatrix(m1, m2, true);
		long t1 = timer1.getTime();
		Timer timer2 = new Timer();
		timer2.startTimer();

		System.out
				.println("Перемножаем лоскуты первой матрицы на 2ю и кладем в контейнер");
		Snip sourceSnip = null;
		Snip multSnip = null;
		ContainerOfSnips contResp = new ContainerOfSnips(3,
				container.getSnipsXLength());

		long time2 = 0;
		Multiplication mult2 = Multiplication.newInstance();
		for (int s = 0; s < container.getSnips().length; s++) {
			sourceSnip = container.getSnipByIndex(s);

			multSnip = mult2.snipOnMatrix(sourceSnip, m2, true);
			time2 += mult2.getTime();
			contResp.setSnipByIndex(multSnip, s);
		}
		long t2 = timer2.getTime();

		System.out.println("Перемножение матриц заняло " + mult1.getTime()
				+ " мс");
		System.out.println("Перемножение 2й матрицы и лоскутов 1й заняло "
				+ time2 + " мс");

		System.out.println("Перемножение матриц (по внешнему таймеру) заняло "
				+ t1 + " мс");
		System.out
				.println("Перемножение 2й матрицы и лоскутов 1й заняло (по внешнему таймеру) заняло "
						+ t2 + " мс");
		// Matrix mComplex = contResp.toMatrix();
		// System.out
		// .println("\n \n Перемножение матрицы 2 на контейнер снипов первой матрицы дает: \n"
		// + mComplex + "\n");
		// System.out.println("\n \n Простое перемножение матриц дает :\n" +
		// m3);

	}

	/**
	 * Генерируем и перемножаем две матрицы
	 * 
	 * @param h
	 *            шаг расчетов, прибавляется к стороне квадратной матрицы
	 * @param startValue
	 *            стартовая ширина и высота
	 * @param endValue
	 *            конечная ширина и высота
	 * @throws Exception
	 */
	@SuppressWarnings("unused")
	private static void sc1(int h, int startValue, int endValue)
			throws Exception {
		int val = startValue;

		for(int i = val; i <= endValue; i+=h) {
			Matrix m1 = Generator
					.generateUnCompressedHorisontalMatrix(val, val, 0.2);
			Matrix m2 = Generator
					.generateUnCompressedHorisontalMatrix(val, val, 0.2);
			Matrix m1c = null;
			Matrix m2c = null;
				m1c = Compressor.compressMatrix(m1);
				m2c = Compressor.compressMatrix(m2);
			Timer timer = new Timer();
			timer.startTimer();
			Matrix m3c = Multiplication.newInstance().matrixOnMatrix(m1c, m2c,
					false);
			// System.out.println(m3 + "\n");
			System.out.println(val + " X " + val + " - " + timer.getTime()
					+ " мс." + "cжатый");
			
			timer.startTimer();
			Matrix m3 = Multiplication.newInstance().matrixOnMatrix(m1, m2,
					false);
			System.out.println(val + " X " + val + " - " + timer.getTime()
					+ " мс." + "разреженный");
			val += h;
		}

	}

	/**
	 * Генерируем и перемножаем две матрицы c разрезанием второй на лоскуты
	 * 
	 * @param h
	 *            шаг расчетов, прибавляется к стороне квадратной матрицы
	 * @param startValue
	 *            стартовая ширина и высота
	 * @param endValue
	 *            конечная ширина и высота
	 * @param procs
	 *            количество процессоров
	 * @param doZip
	 *            нужно ли сжимать матрицу и лоскуты перед расчетом
	 * @throws Exception
	 */
	private static void sc2(int h, int startValue, int endValue, int procs,
			boolean doZip) throws Exception {
		int val = startValue;

		while (val <= endValue) {
			Matrix m1 = Generator
					.generateUnCompressedHorisontalMatrix(val, val, 0.2);

			Matrix m2 = Generator
					.generateUnCompressedHorisontalMatrix(val, val, 0.2);

			ContainerOfSnips containerOfSnips = Cutter.cutMatrixHorizontal(m2,
					procs);
			Snip snip1 = containerOfSnips.getSnipByIndex(0);
			Snip snip2 = containerOfSnips.getSnipByIndex(1);
			Snip snip3 = containerOfSnips.getSnipByIndex(2);
			if (doZip) {
				m1 = Compressor.compressMatrix(m1);
				for (int i = 0; i < procs; i++) {
					Snip s = containerOfSnips.getSnipByIndex(i);
					s = Compressor.compressSnip(s);
					containerOfSnips.setSnipByIndex(s, i);
				}
			}
			Timer timer = new Timer();
			timer.startTimer();

			ContainerOfSnips multContainerOfSnips = new ContainerOfSnips(procs,
					snip1.getXlength());

			for (int i = 0; i < procs; i++) {

			}
			Snip multSnip1 = Multiplication.newInstance().snipOnMatrix(snip1,
					m1, false);
			Snip multSnip2 = Multiplication.newInstance().snipOnMatrix(snip2,
					m1, false);
			Snip multSnip3 = Multiplication.newInstance().snipOnMatrix(snip3,
					m1, false);

			multContainerOfSnips.setSnipByIndex(multSnip1, 0);
			multContainerOfSnips.setSnipByIndex(multSnip2, 1);
			multContainerOfSnips.setSnipByIndex(multSnip3, 2);
			// System.out.println(multContainerOfSnips + "\n");
			System.out.println(val + " X " + val + " - " + timer.getTime()
					+ " мс.");
			val += h;
		}

	}

}
